/**
 *******************************************************************************
 * @file  mcan/mcan_fd/source/main.c
 * @brief Main program of MCAN FD for the Device Driver Library.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2023-05-31       CDT             First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by XHSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "main.h"

/**
 * @addtogroup HC32F448_DDL_Examples
 * @{
 */

/**
 * @addtogroup MCAN
 * @{
 */

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
#define MCAU_UNIT1                      (1U)
#define MCAU_UNIT2                      (2U)
#define MCAU_UNIT_SEL                   MCAU_UNIT1

#if (MCAU_UNIT_SEL == MCAU_UNIT1)
#define MCAN_UNIT                       (CM_MCAN1)
#define MCAN_PERIPH_CLK                 (FCG1_PERIPH_MCAN1)
#define MCAN_CLK_UNIT                   (CLK_MCAN1)
#define MCAN_CLK_SRC                    (CLK_MCANCLK_SYSCLK_DIV5)
/* Pin */
#define MCAN_TX_PORT                    (GPIO_PORT_C)
#define MCAN_TX_PIN                     (GPIO_PIN_12)
#define MCAN_TX_PIN_FUNC                (GPIO_FUNC_56)
#define MCAN_RX_PORT                    (GPIO_PORT_D)
#define MCAN_RX_PIN                     (GPIO_PIN_00)
#define MCAN_RX_PIN_FUNC                (GPIO_FUNC_57)
/* IRQ */
#define MCAN_INT0_PRIO                  (DDL_IRQ_PRIO_03)
#define MCAN_INT0_SRC                   (INT_SRC_MCAN1_INT0)
#define MCAN_INT0_IRQn                  (MCAN1_INT0_IRQn)
#define MCAN_INT_LINE0_HANDLER          MCAN1_INT0_Handler
#define MCAN_INT1_PRIO                  (DDL_IRQ_PRIO_03)
#define MCAN_INT1_SRC                   (INT_SRC_MCAN1_INT1)
#define MCAN_INT1_IRQn                  (MCAN1_INT1_IRQn)
#define MCAN_INT_LINE1_HANDLER          MCAN1_INT1_Handler

#elif (MCAU_UNIT_SEL == MCAU_UNIT2)
#define MCAN_UNIT                       (CM_MCAN2)
#define MCAN_PERIPH_CLK                 (FCG1_PERIPH_MCAN2)
#define MCAN_CLK_UNIT                   (CLK_MCAN2)
#define MCAN_CLK_SRC                    (CLK_MCANCLK_SYSCLK_DIV5)
/* Pin */
#define MCAN_TX_PORT                    (GPIO_PORT_H)
#define MCAN_TX_PIN                     (GPIO_PIN_02)
#define MCAN_TX_PIN_FUNC                (GPIO_FUNC_56)
#define MCAN_RX_PORT                    (GPIO_PORT_E)
#define MCAN_RX_PIN                     (GPIO_PIN_04)
#define MCAN_RX_PIN_FUNC                (GPIO_FUNC_57)
/* IRQ */
#define MCAN_INT0_PRIO                  (DDL_IRQ_PRIO_03)
#define MCAN_INT0_SRC                   (INT_SRC_MCAN2_INT0)
#define MCAN_INT0_IRQn                  (MCAN2_INT0_IRQn)
#define MCAN_INT_LINE0_HANDLER          MCAN2_INT0_Handler
#define MCAN_INT1_PRIO                  (DDL_IRQ_PRIO_03)
#define MCAN_INT1_SRC                   (INT_SRC_MCAN2_INT1)
#define MCAN_INT1_IRQn                  (MCAN2_INT1_IRQn)
#define MCAN_INT_LINE1_HANDLER          MCAN2_INT1_Handler

#else
#error "Not supported selection."
#endif

/* Interrupt */
#define MCAN_RX_INT_SEL                 (MCAN_INT_RX_FIFO0_NEW_MSG | \
                                         MCAN_INT_RX_FIFO1_NEW_MSG | \
                                         MCAN_INT_RX_HPM | \
                                         MCAN_INT_RX_BUF_NEW_MSG)
#define MCAN_TX_INT_SEL                 (MCAN_INT_TX_CPLT | \
                                         MCAN_INT_TX_EVT_FIFO_NEW_DATA | \
                                         MCAN_INT_BUS_OFF)

#define MCAN_INT0_SEL                   MCAN_RX_INT_SEL
#define MCAN_INT1_SEL                   MCAN_TX_INT_SEL

/* Message RAM */
/* Each standard filter element size is 4 bytes */
#define MCAN_STD_FILTER_NUM             (3U)
/* Each extended filter element size is 8 bytes */
#define MCAN_EXT_FILTER_NUM             (3U)
/* Each Rx FIFO0 element size is 64+8 bytes */
#define MCAN_RX_FIFO0_NUM               (3U)
#define MCAN_RX_FIFO0_DATA_FIELD_SIZE   MCAN_DATA_SIZE_64BYTE
/* Each Rx FIFO1 element size is 64+8 bytes */
#define MCAN_RX_FIFO1_NUM               (3U)
#define MCAN_RX_FIFO1_DATA_FIELD_SIZE   MCAN_DATA_SIZE_64BYTE
/* Each Rx buffer element size is 64+8 bytes */
#define MCAN_RX_BUF_NUM                 (3U)
#define MCAN_RX_BUF_DATA_FIELD_SIZE     MCAN_DATA_SIZE_64BYTE
/* Each Tx buffer element size is 64+8 bytes */
#define MCAN_TX_BUF_NUM                 (4U)
#define MCAN_TX_FIFO_NUM                (2U)
#define MCAN_TX_BUF_DATA_FIELD_SIZE     MCAN_DATA_SIZE_64BYTE
#define MCAN_TX_NOTIFICATION_BUF        (MCAN_TX_BUF0 | MCAN_TX_BUF1 | MCAN_TX_BUF2)
/* Each extended filter element size is 8 bytes */
#define MCAN_TX_EVT_NUM                 (3U)

/* Filter */
#define MCAN_CFG_IGNOR                  (0U)
/* Accept standard frames with ID from 0x110 to 0x11F and store to Rx FIFO1 */
#define MCAN_STD_FILTER0                {.u32IdType = MCAN_STD_ID, .u32FilterIndex = 0U, .u32FilterType = MCAN_FILTER_RANGE, \
                                         .u32FilterConfig = MCAN_FILTER_TO_RX_FIFO1, .u32FilterId1 = 0x110UL, \
                                         .u32FilterId2 = 0x11FUL,}
/* Accept standard frame with ID 0x120 and store to dedicated Rx buffer 0 */
#define MCAN_STD_FILTER1                {.u32IdType = MCAN_STD_ID, .u32FilterIndex = 1U, .u32FilterType = MCAN_CFG_IGNOR, \
                                         .u32FilterConfig = MCAN_FILTER_TO_RX_BUF, .u32FilterId1 = 0x120UL, \
                                         .u32FilterId2 = MCAN_CFG_IGNOR, .u32RxBufferIndex = MCAN_RX_BUF0}
/* Accept standard frames with ID 0x130 and 0x138 and store to Rx FIFO1 */
#define MCAN_STD_FILTER2                {.u32IdType = MCAN_STD_ID, .u32FilterIndex = 2U, .u32FilterType = MCAN_FILTER_DUAL, \
                                         .u32FilterConfig = MCAN_FILTER_HP_TO_RX_FIFO1, .u32FilterId1 = 0x130UL, \
                                         .u32FilterId2 = 0x138UL}

/* Accept extended frames with ID from 0x12345110 to 0x1234511F and store to Rx FIFO0 */
#define MCAN_EXT_FILTER0                {.u32IdType = MCAN_EXT_ID, .u32FilterIndex = 0U, .u32FilterType = MCAN_FILTER_MASK, \
                                         .u32FilterConfig = MCAN_FILTER_TO_RX_FIFO0, .u32FilterId1 = 0x12345110UL, \
                                         .u32FilterId2 = 0x1FFFFFF0UL,}
/* Accept extended frame with ID 0x12345120 and store to dedicated Rx buffer 1 */
#define MCAN_EXT_FILTER1                {.u32IdType = MCAN_EXT_ID, .u32FilterIndex = 1U, .u32FilterType = MCAN_CFG_IGNOR, \
                                         .u32FilterConfig = MCAN_FILTER_TO_RX_BUF, .u32FilterId1 = 0x12345120UL, \
                                         .u32FilterId2 = MCAN_CFG_IGNOR, .u32RxBufferIndex = MCAN_RX_BUF1}
/* Accept standard frames with ID 0x12345130 and 0x12345138 and store to Rx FIFO0 */
#define MCAN_EXT_FILTER2                {.u32IdType = MCAN_EXT_ID, .u32FilterIndex = 2U, .u32FilterType = MCAN_FILTER_DUAL, \
                                         .u32FilterConfig = MCAN_FILTER_HP_TO_RX_FIFO0, .u32FilterId1 = 0x12345130UL, \
                                         .u32FilterId2 = 0x12345138UL}

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
static void McanCommClockConfig(void);
static void McanInitConfig(void);
static void McanIrqConfig(void);
static void McanPinConfig(void);
static void McanPhyEnable(void);

static void McanSampleTx(void);

static void McanLoadTxMsg(stc_mcan_tx_msg_t *pstcTxMsg, stc_mcan_rx_msg_t *pstcRxMsg);

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 * @brief  Main function of mcan_fd project
 * @param  None
 * @retval int32_t return value, if needed
 */
int32_t main(void)
{
    /* Register write enable for some required peripherals. */
    LL_PERIPH_WE(LL_PERIPH_ALL);

    BSP_CLK_Init();
    BSP_IO_Init();
    DDL_PrintfInit(BSP_PRINTF_DEVICE, 115200UL, BSP_PRINTF_Preinit);

    McanCommClockConfig();
    McanInitConfig();
    McanIrqConfig();
    McanPinConfig();
    McanPhyEnable();

    /* Register write protected for some required peripherals. */
    LL_PERIPH_WP(LL_PERIPH_ALL);

    /*********************************************************************************************/

    /* Start the MCAN module */
    MCAN_Start(MCAN_UNIT);

    /*********************************************************************************************/
    McanSampleTx();

    for (;;) {
    }
}

/**
 * @brief  Specifies communication clock.
 * @param  None
 * @retval None
 */
static void McanCommClockConfig(void)
{
    CLK_SetCANClockSrc(MCAN_CLK_UNIT, MCAN_CLK_SRC);
}

/**
 * @brief  MCAN initial configuration.
 * @param  None
 * @retval None
 */
static void McanInitConfig(void)
{
    stc_mcan_init_t stcMcanInit;
    stc_mcan_filter_t stcStdFilterList[MCAN_STD_FILTER_NUM] = {
        MCAN_STD_FILTER0, MCAN_STD_FILTER1, MCAN_STD_FILTER2
    };
    stc_mcan_filter_t stcExtFilterList[MCAN_EXT_FILTER_NUM] = {
        MCAN_EXT_FILTER0, MCAN_EXT_FILTER1, MCAN_EXT_FILTER2
    };

    (void)MCAN_StructInit(&stcMcanInit);
    stcMcanInit.u32Mode = MCAN_MD_NORMAL;
    stcMcanInit.u32FrameFormat = MCAN_FRAME_FD_BRS;
    /* Classic CAN. Baudrate 1Mbps, sample point 80% */
    stcMcanInit.stcCanClassic.u32Prescaler     = 1U;
    stcMcanInit.stcCanClassic.u32TimeSeg1      = 32U;
    stcMcanInit.stcCanClassic.u32TimeSeg2      = 8U;
    stcMcanInit.stcCanClassic.u32SyncJumpWidth = 8U;
    /* FD CAN. Baudrate 4Mbps, sample point 80% */
    stcMcanInit.stcCanFd.u32FdIso              = MCAN_FD_ISO;
    stcMcanInit.stcCanFd.u32Prescaler          = 1U;
    stcMcanInit.stcCanFd.u32TimeSeg1           = 8U;
    stcMcanInit.stcCanFd.u32TimeSeg2           = 2U;
    stcMcanInit.stcCanFd.u32SyncJumpWidth      = 2U;
    stcMcanInit.stcCanFd.u32TDC                = MCAN_FD_TDC_ENABLE;
    stcMcanInit.stcCanFd.u32SspOffset          = 8U;
    stcMcanInit.stcCanFd.u32TdcFilter          = 0U;
    /* Message RAM */
    stcMcanInit.stcMsgRam.u32AddrOffset        = 0U;
    stcMcanInit.stcMsgRam.u32StdFilterNum      = MCAN_STD_FILTER_NUM;
    stcMcanInit.stcMsgRam.u32ExtFilterNum      = MCAN_EXT_FILTER_NUM;
    stcMcanInit.stcMsgRam.u32RxFifo0Num        = MCAN_RX_FIFO0_NUM;
    stcMcanInit.stcMsgRam.u32RxFifo0DataSize   = MCAN_RX_FIFO0_DATA_FIELD_SIZE;
    stcMcanInit.stcMsgRam.u32RxFifo1Num        = MCAN_RX_FIFO1_NUM;
    stcMcanInit.stcMsgRam.u32RxFifo1DataSize   = MCAN_RX_FIFO1_DATA_FIELD_SIZE;
    stcMcanInit.stcMsgRam.u32RxBufferNum       = MCAN_RX_BUF_NUM;
    stcMcanInit.stcMsgRam.u32RxBufferDataSize  = MCAN_RX_BUF_DATA_FIELD_SIZE;
    stcMcanInit.stcMsgRam.u32TxBufferNum       = MCAN_TX_BUF_NUM;
    stcMcanInit.stcMsgRam.u32TxFifoQueueNum    = MCAN_TX_FIFO_NUM;
    stcMcanInit.stcMsgRam.u32TxFifoQueueMode   = MCAN_TX_FIFO_MD;
    stcMcanInit.stcMsgRam.u32TxDataSize        = MCAN_TX_BUF_DATA_FIELD_SIZE;
    stcMcanInit.stcMsgRam.u32TxEventNum        = MCAN_TX_EVT_NUM;
    /* Acceptance filter */
    stcMcanInit.stcFilter.pstcStdFilterList     = stcStdFilterList;
    stcMcanInit.stcFilter.pstcExtFilterList     = stcExtFilterList;
    stcMcanInit.stcFilter.u32StdFilterConfigNum = stcMcanInit.stcMsgRam.u32StdFilterNum;
    stcMcanInit.stcFilter.u32ExtFilterConfigNum = stcMcanInit.stcMsgRam.u32ExtFilterNum;

    FCG_Fcg1PeriphClockCmd(MCAN_PERIPH_CLK, DISABLE);
    FCG_Fcg1PeriphClockCmd(MCAN_PERIPH_CLK, ENABLE);
    (void)MCAN_Init(MCAN_UNIT, &stcMcanInit);

    /* The Tx buffer can cause transmission completed completed interrupt
       only when its own transmission completed interrupt is enabled. */
    MCAN_TxBufferNotificationCmd(MCAN_UNIT, MCAN_TX_NOTIFICATION_BUF, MCAN_INT_TX_CPLT, ENABLE);

    MCAN_IntCmd(MCAN_UNIT, MCAN_INT0_SEL, MCAN_INT_LINE0, ENABLE);
    MCAN_IntCmd(MCAN_UNIT, MCAN_INT1_SEL, MCAN_INT_LINE1, ENABLE);
}

/**
 * @brief  CAN interrupt configuration.
 * @param  None
 * @retval None
 */
static void McanIrqConfig(void)
{
    NVIC_ClearPendingIRQ(MCAN_INT0_IRQn);
    NVIC_SetPriority(MCAN_INT0_IRQn, MCAN_INT0_PRIO);
    NVIC_EnableIRQ(MCAN_INT0_IRQn);

    NVIC_ClearPendingIRQ(MCAN_INT1_IRQn);
    NVIC_SetPriority(MCAN_INT1_IRQn, MCAN_INT0_PRIO);
    NVIC_EnableIRQ(MCAN_INT1_IRQn);
}

/**
 * @brief  Specifies pin function for TXD and RXD.
 * @param  None
 * @retval None
 */
static void McanPinConfig(void)
{
    GPIO_SetFunc(MCAN_TX_PORT, MCAN_TX_PIN, MCAN_TX_PIN_FUNC);
    GPIO_SetFunc(MCAN_RX_PORT, MCAN_RX_PIN, MCAN_RX_PIN_FUNC);
}

/**
 * @brief  Set CAN PHY STB pin as low.
 * @param  None
 * @retval None
 */
static void McanPhyEnable(void)
{
    BSP_CAN_STB_IO_Init();
    /* Set PYH STB pin as low. */
    BSP_CAN_STBCmd(EIO_PIN_RESET);
}

/**
 * @brief  MCAN transmit.
 * @param  None
 * @retval None
 */
static void McanSampleTx(void)
{
    stc_mcan_tx_msg_t stcTxMsg = {
        .ID = 0x777UL,
        .IDE = 0U,
        .DLC = MCAN_DLC8,
        .u32TxBuffer = MCAN_TX_BUF0,
        .au8Data = {1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U},
    };
    (void)MCAN_AddMsgToTxBuffer(MCAN_UNIT, &stcTxMsg);
    MCAN_EnableTxBufferRequest(MCAN_UNIT, stcTxMsg.u32TxBuffer);

    stcTxMsg.ID = 0x17777777UL;
    stcTxMsg.IDE = 1U;
    (void)MCAN_AddMsgToTxFifoQueue(MCAN_UNIT, &stcTxMsg);
}

/**
 * @brief  MCAN interrupt line 0 IRQ handler.
 * @param  None
 * @retval None
 */
void MCAN_INT_LINE0_HANDLER(void)
{
    uint32_t u32RxFIFO;
    stc_mcan_rx_msg_t stcRxMsg;
    stc_mcan_tx_msg_t stcTxMsg;
    stc_mcan_hpm_status_t stcHpmStatus;

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_RX_FIFO0_NEW_MSG) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_RX_FIFO0_NEW_MSG);
        /* Rx FIFO 0 New Message */
        DDL_Printf("Rx FIFO 0 new message\r\n");
        if (MCAN_GetRxMsg(MCAN_UNIT, MCAN_RX_FIFO0, &stcRxMsg) == LL_OK) {
            McanLoadTxMsg(&stcTxMsg, &stcRxMsg);
            stcTxMsg.u32TxBuffer = MCAN_TX_BUF0;
            /* Transmit message via dedicated Tx buffer */
            if (MCAN_AddMsgToTxBuffer(MCAN_UNIT, &stcTxMsg) == LL_OK) {
                MCAN_EnableTxBufferRequest(MCAN_UNIT, stcTxMsg.u32TxBuffer);
            } else {
                /* The specified dedicated Tx buffer is busy. */
            }
        } else {
            /* Exception */
        }
    }

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_RX_FIFO1_NEW_MSG) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_RX_FIFO1_NEW_MSG);
        /* Rx FIFO 1 New Message */
        DDL_Printf("Rx FIFO 1 new message\r\n");
        if (MCAN_GetRxMsg(MCAN_UNIT, MCAN_RX_FIFO1, &stcRxMsg) == LL_OK) {
            McanLoadTxMsg(&stcTxMsg, &stcRxMsg);
            stcTxMsg.u32TxBuffer = MCAN_TX_BUF1;
            /* Transmit message via dedicated Tx buffer */
            if (MCAN_AddMsgToTxBuffer(MCAN_UNIT, &stcTxMsg) == LL_OK) {
                MCAN_EnableTxBufferRequest(MCAN_UNIT, stcTxMsg.u32TxBuffer);
            } else {
                /* The specified dedicated Tx buffer is busy. */
            }
        } else {
            /* Exception */
        }
    }

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_RX_HPM) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_RX_HPM);
        /* High Priority Message */
        DDL_Printf("High priority message received\r\n");
        /* Get high priority message status */
        (void)MCAN_GetHighPriorityMsgStatus(MCAN_UNIT, &stcHpmStatus);
        if (stcHpmStatus.u8MsgStorageIndex == MCAN_HPM_STORED_IN_RX_FIFO0) {
            DDL_Printf("High priority message stored in Rx FIFO0\r\n");
            u32RxFIFO = MCAN_RX_FIFO0;
        } else {
            DDL_Printf("High priority message stored in Rx FIFO1\r\n");
            u32RxFIFO = MCAN_RX_FIFO1;
        }
        if (MCAN_GetRxMsg(MCAN_UNIT, u32RxFIFO, &stcRxMsg) == LL_OK) {
            McanLoadTxMsg(&stcTxMsg, &stcRxMsg);
            /* Transmit message via Tx FIFO/Queue */
            if (MCAN_AddMsgToTxFifoQueue(MCAN_UNIT, &stcTxMsg) != LL_OK) {
                /* Tx FIFO full */
                DDL_Printf("Tx FIFO full\r\n");
            }
        } else {
            /* Exception */
        }
    }

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_RX_BUF_NEW_MSG) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_RX_BUF_NEW_MSG);
        /* Message stored to Dedicated Rx Buffer */
        DDL_Printf("Message stored to dedicated Rx buffer\r\n");
        if (MCAN_CheckRxBufferMsgAvailable(MCAN_UNIT, MCAN_RX_BUF0) == LL_OK) {
            if (MCAN_GetRxMsg(MCAN_UNIT, MCAN_RX_BUF0, &stcRxMsg) == LL_OK) {
                DDL_Printf("Dedicated Rx buffer0 received\r\n");
                McanLoadTxMsg(&stcTxMsg, &stcRxMsg);
                /* Transmit message via Tx FIFO/Queue */
                if (MCAN_AddMsgToTxFifoQueue(MCAN_UNIT, &stcTxMsg) != LL_OK) {
                    /* Tx FIFO full */
                    DDL_Printf("Tx FIFO full\r\n");
                }
            } else {
                /* Exception */
            }
        }

        if (MCAN_CheckRxBufferMsgAvailable(MCAN_UNIT, MCAN_RX_BUF1) == LL_OK) {
            if (MCAN_GetRxMsg(MCAN_UNIT, MCAN_RX_BUF1, &stcRxMsg) == LL_OK) {
                DDL_Printf("Dedicated Rx buffer1 received\r\n");
                McanLoadTxMsg(&stcTxMsg, &stcRxMsg);
                /* Transmit message via Tx FIFO/Queue */
                if (MCAN_AddMsgToTxFifoQueue(MCAN_UNIT, &stcTxMsg) != LL_OK) {
                    /* Tx FIFO full */
                    DDL_Printf("Tx FIFO full\r\n");
                }
            } else {
                /* Exception */
            }
        }
    }

    __DSB();  /* Arm Errata 838869 */
}

/**
 * @brief  MCAN interrupt line 1 IRQ handler.
 * @param  None
 * @retval None
 */
void MCAN_INT_LINE1_HANDLER(void)
{
    stc_mcan_tx_event_t stcTxEvent;

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_TX_CPLT) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_TX_CPLT);
        /* Transmission Completed */
        DDL_Printf("Transmission completed\r\n");
        /* User code if needed */
    }

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_TX_EVT_FIFO_NEW_DATA) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_TX_EVT_FIFO_NEW_DATA);
        /* Tx Event FIFO New Entry */
        DDL_Printf("Tx event FIFO new entry\r\n");
        if (MCAN_GetTxEvent(MCAN_UNIT, &stcTxEvent) == LL_OK) {
            /* Use the Tx event if needed */
            DDL_Printf("Tx event: ID %.8x\r\n", (unsigned int)stcTxEvent.ID);
            DDL_Printf("Tx event: message marker %u\r\n", (uint8_t)stcTxEvent.u32MsgMarker);
        }
    }

    if (MCAN_GetStatus(MCAN_UNIT, MCAN_FLAG_BUS_OFF) == SET) {
        MCAN_ClearStatus(MCAN_UNIT, MCAN_FLAG_BUS_OFF);
        /* The operation when Bus Off.
           The device will then wait for 129 occurrences of Bus Idle(129 * 11 consecutive recessive bits)
           before resuming normal operation. */
        MCAN_Start(MCAN_UNIT);
    }

    __DSB();  /* Arm Errata 838869 */
}

/**
 * @brief  Load Tx message from received message
 * @param  [in]  pstcTxMsg              Pointer to the message to be transmitted.
 * @param  [in]  pstcRxMsg              Pointer to the received message.
 * @retval None
 */
static void McanLoadTxMsg(stc_mcan_tx_msg_t *pstcTxMsg, stc_mcan_rx_msg_t *pstcRxMsg)
{
    static uint8_t u8TxMarker = 0U;
    *pstcTxMsg = *((stc_mcan_tx_msg_t *)pstcRxMsg);
    pstcTxMsg->au8Data[0U] = u8TxMarker;
    pstcTxMsg->ID &= 0xFFFFF0FFUL;
    pstcTxMsg->ID |= 0x300UL;
    pstcTxMsg->ESI = 0U;
    pstcTxMsg->u32StoreTxEvent = 1U;
    pstcTxMsg->u32MsgMarker = u8TxMarker++;
}

/**
 * @}
 */

/**
 * @}
 */

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
